package com.sch.www.codeGenerator.base;

import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * BaseServices接口
 * Created by admin on 2017/01/07.
 */
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public abstract class BaseServicesComplexImp<Record extends BaseEntity, RecordWithBLOBs extends Record, Example extends BaseExample, Mapper extends BaseMapper<Record, RecordWithBLOBs, Example>, CurrentProxy>
        implements BaseServicesComplex<Record, RecordWithBLOBs> {

    @Autowired
    private Mapper mapper;

    CurrentProxy currentProxy;

    private boolean openDataAuthority = false;

    public boolean isOpenDataAuthority() {
        return openDataAuthority;
    }

    public void setOpenDataAuthority(boolean openDataAuthority) {
        this.openDataAuthority = openDataAuthority;
    }

    protected void postHandlerForDataAuthority(Example example) {
        if (openDataAuthority) {
            throw new RuntimeException("openDataAuthority=true 开启了数据权限，应重写postHandlerForDataAuthority方法");
        }
    }

    protected Mapper getMapper() {
        return mapper;
    }

    protected CurrentProxy getCurrentProxy() {
        if (currentProxy == null) {
            currentProxy = (CurrentProxy) AopContext.currentProxy();
        }
        return currentProxy;
    }

    protected abstract Example getExampleNewInstance();

    protected abstract String getTableName();


    //================================
    //  START impl BaseServicesComplex
    //================================


    @Override
    public RecordWithBLOBs selectById(String id) {
        if (id == null || id.equals("")) {
            return null;
        } else {
            return getMapper().selectByPrimaryKey(id);
        }
    }

    @Override
    public List<Record> selectById(Collection<String> idList) {
        if (idList == null || idList.isEmpty()) {
            return Collections.EMPTY_LIST;
        } else {
            Example example = getExampleNewInstance();
            example.createCriteria().andIdIn(idList instanceof List ? (List) idList : new ArrayList<>(idList));
            return getMapper().selectByExample(example);
        }
    }

    @Transactional
    @Override
    public int insert(RecordWithBLOBs... recordWithBLOBss) {
        if (isNull(recordWithBLOBss)) {
            return 0;
        } else {
            pretreatmentInsert(recordWithBLOBss);
            if (recordWithBLOBss.length == 1) {
                return getMapper().insert(recordWithBLOBss[0]);
            } else {
                return insertBatch(recordWithBLOBss);
            }
        }
    }

    protected int insertBatch(RecordWithBLOBs... recordWithBLOBss) {
        for (RecordWithBLOBs record : recordWithBLOBss) {
            getMapper().insert(record);
        }
        return recordWithBLOBss.length;
    }


    @Transactional
    @Override
    public int insertSelective(RecordWithBLOBs... recordWithBLOBss) {
        if (isNull(recordWithBLOBss)) {
            return 0;
        } else {
            pretreatmentInsert(recordWithBLOBss);
            if (recordWithBLOBss.length == 1) {
                return getMapper().insertSelective(recordWithBLOBss[0]);
            } else {
                return insertBatchSelective(recordWithBLOBss);
            }
        }
    }

    protected int insertBatchSelective(RecordWithBLOBs... recordWithBLOBss) {
        for (RecordWithBLOBs record : recordWithBLOBss) {
            getMapper().insertSelective(record);
        }
        return recordWithBLOBss.length;
    }

    @Override
    public boolean updateById(Record record) {
        if (record == null) {
            return false;
        } else {
            pretreatmentUpdate(record);
            int result = getMapper().updateByPrimaryKey(record);
            return result == 1 ? true : false;
        }
    }

    @Override
    public boolean updateByIdSelective(RecordWithBLOBs recordWithBLOBs) {
        if (recordWithBLOBs == null) {
            return false;
        } else {
            pretreatmentUpdate(recordWithBLOBs);
            int result = getMapper().updateByPrimaryKeySelective(recordWithBLOBs);
            return result == 1 ? true : false;
        }
    }

    @Override
    public boolean updateByIdWithBLOBs(RecordWithBLOBs recordWithBLOBs) {
        if (recordWithBLOBs == null) {
            return false;
        } else {
            pretreatmentUpdate(recordWithBLOBs);
            int result = getMapper().updateByPrimaryKeyWithBLOBs(recordWithBLOBs);
            return result == 1 ? true : false;

        }
    }


    @Transactional
    @Override
    public int deleteById(String... ids) {
        if (isNull(ids)) {
            return 0;
        } else if (ids.length == 1) {
            return getMapper().deleteByPrimaryKey(ids[0]);
        } else {
            Example example = getExampleNewInstance();
            example.createCriteria().andIdIn(Arrays.asList(ids));
            return getMapper().deleteByExample(example);
        }
    }

    public void handInsertBlankId(BaseEntity baseEntity) {
        baseEntity.setId(UUID.randomUUID().toString());
    }

    private void pretreatmentInsert(BaseEntity... records) {
        Date nowDate = new Date();
        for (BaseEntity record : records) {
            record.setUpdateTime(nowDate);
            record.setCreateTime(nowDate);
            if (record.getId() == null || record.getId().trim().equals("")) {
                handInsertBlankId(record);
            }
        }
    }

    protected void pretreatmentUpdate(BaseEntity... records) {
        Date nowDate = new Date();
        for (BaseEntity record : records) {
            record.setUpdateTime(nowDate);
        }
    }

    protected boolean isNull(Object... objects) {
        if (objects == null || objects.length == 0 || objects[0] == null) {
            return true;
        } else {
            return false;
        }
    }

    protected String likePacking(String field) {
        return "%" + field + "%";
    }


    //================================
    //  END impl BaseServicesComplex
    //================================


}